package cn.itsource.common;

import cn.itsource.domain.User;
import com.sun.org.apache.xml.internal.serialize.Printer;
import org.springframework.cglib.proxy.*;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MemoryTest {


    public static void main(String[] args) {
        //不会引起永久代溢出
//        testPergemOutOfMemory1();
        //永久代溢出
        testPergemOutOfMemory2();

        //jvm 内存溢出
        //testNativeMethodOutOfMemory();
        //栈内存溢出
        //testStackOutOfMemory();
        //堆溢出
        //testOutOfHeapMemory();

    }

    //栈深度溢出

//    public static void  testStackOverFlow(){
//
//        BlowUpJVM.testStackOverFlow();
//
//    }

    //不会引起永久代溢出

    public static void testPergemOutOfMemory1(){

        //方法一失败

        List<String> list = new ArrayList<String>();

        while(true){

            list.add(UUID.randomUUID().toString().intern());

        }

    }

    //永久代溢出

    public static void testPergemOutOfMemory2(){

        try {

            while (true) {

                Enhancer enhancer = new Enhancer();

                enhancer.setSuperclass(User.class);

                enhancer.setUseCache(false);

                enhancer.setCallback(new MethodInterceptor() {

                    @Override

                    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {

                        return proxy.invokeSuper(obj, args);

                    }

                });

                enhancer.create();

            }

        }

        catch (Exception e){

            e.printStackTrace();

        }

    }

    //不会引起永久代溢出

    public static void testPergemOutOfMemory3(){

        while(true){

            final User oom = new User();

            Proxy.newProxyInstance(oom.getClass().getClassLoader(), oom.getClass().getInterfaces(), new InvocationHandler() {

                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                    Object result = method.invoke(oom, args);

                    return result;

                }

            });

        }

    }

    //本地方法栈溢出

    public static void testNativeMethodOutOfMemory(){

        int j = 0;

        while(true){

            //Printer.println(j++);

            ExecutorService executors = Executors.newFixedThreadPool(50);

            int i=0;

            while(i++<10){

                executors.submit(new Runnable() {

                    public void run() {

                    }

                });

            }

        }

    }

    //JVM内存溢出

    public static void testStackOutOfMemory(){

        while (true) {

            Thread thread = new Thread(new Runnable() {

                public void run() {

                    while(true){

                    }

                }

            });

            thread.start();

        }

    }

    //堆溢出

    public static void testOutOfHeapMemory(){

        List<StringBuffer> list = new ArrayList<StringBuffer>();

        while(true){

            StringBuffer B = new StringBuffer();

            for(int i = 0 ; i < 10000 ; i++){

                B.append(i);

            }

            list.add(B);

        }

    }


}
